package com.yangyang.ralearn.common.script;

import org.apache.log4j.Logger

import com.yangyang.ralearn.common.Constants
import com.yangyang.ralearn.common.JEnvironment;
import com.yangyang.ralearn.common.entity.base.ActionLimit;
import com.yangyang.ralearn.common.entity.base.BaseAction;
import com.yangyang.ralearn.common.entity.base.BaseActionModelDef;
import com.yangyang.ralearn.common.entity.base.BasePredicate;
import com.yangyang.ralearn.common.entity.base.ParamedPredicate;
import com.yangyang.ralearn.common.entity.domain.RobotAction;
import com.yangyang.ralearn.common.parser.ProblemParser
import com.yangyang.ralearn.common.types.JObject
import com.yangyang.ralearn.common.types.JType
import com.yangyang.ralearn.server.parser.ParseException
import com.yangyang.ralearn.server.parser.PlanParser

class BaseAlgorithm {

	/**
	 * 根据当前的状态返回理论上可以做的所有action
	 * @param model
	 * @param states
	 * @return
	 */
	public static getAllPossiableAction(BaseActionModelDef model,
			List<BasePredicate> states){
		def possiableActions = new HashSet<BaseAction>()
		possiableActions<<new RobotAction(model.getName(), null)
		def type2Values = [ : ]
		def var2Values = [ : ]
		states.each { state->
			state.getPraramValues().each {
				//println it
				def type = it.getType()
				if(!type2Values[type]) type2Values[type] = new HashSet<JObject>()
				type2Values[type]<< it
			}
		}
		def tempActions = new HashSet<BaseAction>()
		model.mapVar2Type.values().each { entry ->
			if( type2Values[entry.name]){
				tempActions.clear()
				type2Values[entry.name].each { object->
					possiableActions.each {   action->
						if(!action.getValues().contains(object)){
							def newAction = action.clone()
							newAction.getValues().add(object)
							tempActions.add(newAction)
						}
					}
				}
				possiableActions.clear()
				if(tempActions.size() > 0){
					possiableActions.addAll(tempActions)
				}
			}
		}
		return possiableActions
	}

	/**
	 * 获取所有可能的actionmodel
	 * @param name
	 * @param mapVar2Type
	 * @return
	 */
	public static getAllPossiableActionModel(JEnvironment environment,String name,Map<String,JType> mapVar2Type){
		def mapVar2TypeStr = [ : ]
		mapVar2Type.each{ key,value->
			mapVar2TypeStr[key] = value.getName()
		}
		def possiableActionModels = [
			new BaseActionModelDef(environment,name, mapVar2TypeStr, null, null)
		]
		def tempActionModels = new ArrayList<BaseActionModelDef>()
		def possiablePredicates = environment.mapNamePredicateDef.findAll { entry->
			entry.getValue().fit(mapVar2Type)
		}
		possiablePredicates.each { entry->
			def paramedPredicates = ParamedPredicate.parseParamedPredicates(environment,entry.getValue(), mapVar2Type)
			paramedPredicates.each { pre->
				//println pre
				tempActionModels.clear()
				//Logger.getLogger(BaseAlgorithm.class).debug(pre)
				possiableActionModels.each{ model->
					def ActionLimit limit = environment.mapName2ActionLimit.get(model.getName())
					if(!model.preConditions.contains(pre) && model.preConditions.size() < limit.getPreConditionCount() && ParamedPredicate.canTogether(model.preConditions, pre)){
						def newModel = model.clone()
						newModel.getPreConditions().add(pre)
						tempActionModels.add(newModel)
					}
					if(!model.effects.contains(pre) && model.effects.size() < limit.getEffectAddCount()  && ParamedPredicate.canTogether(model.effects, pre)){
						def newModel = model.clone()
						newModel.getEffects().add(pre)
						tempActionModels.add(newModel)
					}
				}
				//println possiableActionModels.size()
				//Logger.getLogger(BaseAlgorithm.class).debug(tempActionModels)
				possiableActionModels.addAll(tempActionModels)
			}

		}

		def finalActionModels = new HashSet<BaseActionModelDef>()
		def subTempActyionModels = new HashSet<BaseActionModelDef>()
		possiableActionModels = possiableActionModels.findAll {
			def ActionLimit limit = environment.mapName2ActionLimit.get(it.getName())
			it.effects.size() == limit.getEffectAddCount() && it.preConditions.size() == limit.getPreConditionCount()
		}
		possiableActionModels.each { model->
			tempActionModels.clear()
			tempActionModels.add(model)
			model.getPreConditions().each { pre->
				subTempActyionModels.clear()
				tempActionModels.each{ tempModel->
					def newModel = tempModel.clone()
					def negPre = pre.clone()
					negPre.setName(Constants.NEG_PREFIX + negPre.getName())
					newModel.getEffects().add(negPre)
					subTempActyionModels.add(newModel)
				}
				tempActionModels.addAll(subTempActyionModels)
			}
			tempActionModels.remove(model)
			finalActionModels.addAll(tempActionModels)
			finalActionModels = finalActionModels.findAll {
				def ActionLimit limit = environment.mapName2ActionLimit.get(it.getName())
				it.effects.size() == limit.getEffectAddCount() + limit.getEffectDeleteCount() &&
						it.preParaCount() == limit.getMapVar2Type().size() && it.effectParaCount() == limit.getMapVar2Type().size()
			}
			//println tempActionModels.size()
		}
		return finalActionModels
	}

}
